package com.yinshan.arface.utils;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Process;
import android.provider.MediaStore;
import android.view.SurfaceHolder;
import android.widget.Toast;

import com.yinshan.arface.FaceView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static android.media.ThumbnailUtils.OPTIONS_RECYCLE_INPUT;
import static android.media.ThumbnailUtils.extractThumbnail;


/**
 * Created by zhangxingsheng on 2017/7/4.
 * 录音接口
 */

public class FaceUtils implements MediaRecorder.OnErrorListener {
    private Camera mCamera;
    private static FaceUtils cameraInter;
    private boolean isPreview = false;
    private Camera.Parameters mParams;
    // Camera nv21格式预览帧的尺寸，默认设置640*480
    private int PREVIEW_WIDTH = 640;
    private int PREVIEW_HEIGHT = 480;
    // 预览帧数据存储数组和缓存数组

    private MediaRecorder mMediaRecorder;
    private long sizePicture = 0;
    private static File videofileDir;// 文件
    private static File imagefileDir;// 文件
    private static Context mContext;
    //文件路径
    private static final String PATH_BASE = Environment.getExternalStorageDirectory().getPath();
    private static final String PATH_VIDEO = PATH_BASE + File.separator + "DCIM/Video";
    private static final String PATH_IMAGE = PATH_BASE + File.separator + "DCIM/Image";
    private static final String FILE_NAME = "record-";
    private static final String FILE_NAME_SUFEIX = ".mp4";
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINESE);// 用于格式化日
    private static String time;
    private static File outFile;

    private FaceUtils() {
    }


    public static synchronized FaceUtils getInstance(Context context) {
        if (cameraInter == null) {
            cameraInter = new FaceUtils();
        }
        mContext = context;
        return cameraInter;
    }

    /**
     * 打开相机 一直开启前置摄像头
     *
     * @param holder
     * @param cameraId
     */
    public void doOpenCamera(SurfaceHolder holder, int cameraId) {
        if (null != mCamera) {
            doDestroyCamera();
            return;
        }
        if (!checkCameraPermission()) {
            Toast.makeText(mContext, "摄像头权限未打开，请打开后再试", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            mCamera = Camera.open(cameraId);
        } catch (Exception e) {
            doDestroyCamera();
            e.printStackTrace();
        }
    }

    /**
     * 返回录制的视频文件
     *
     * @return
     */
    public File getmVecordFile() {
        return outFile;
    }


    /**
     * 删除文件
     */
    public void delFile() {
        try {
            if (outFile != null) {
                File file = new File(outFile.getAbsolutePath());
                if (file.isFile()) {
                    file.delete();
                }
                file.exists();
            }
        } catch (Exception ex) {

        }
    }

    /**
     * 关闭照相机
     */
    public void doDestroyCamera() {
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            isPreview = false;
            mCamera.release();
            mCamera = null;
        }
    }

    /**
     * 重置实例
     */
    public void doDestroyCameraInterface() {
        if (null != cameraInter) {
            cameraInter = null;
        }
    }

    public void doStartPreview(SurfaceHolder holder, float previewRate) {
        if (isPreview) {
            mCamera.stopPreview();
            return;
        }
        if (mCamera != null) {
            mParams = mCamera.getParameters();
            mParams.setPictureFormat(PixelFormat.JPEG);// 设置拍照后存储的图片格式
            mParams.setPreviewFormat(ImageFormat.NV21);// 设置PreviewSize和PictureSize
            mParams.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
            mCamera.setParameters(mParams);
            mCamera.setDisplayOrientation(90);
            List<String> focusModes = mParams.getSupportedFocusModes();
            if (focusModes.contains("continuous-video")) {
                mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            }
            List<Camera.Size> supportedPictureSizes = mParams.getSupportedPictureSizes();
            for (Camera.Size size : supportedPictureSizes) {
                sizePicture = (size.height * size.width) > sizePicture ? size.height * size.width : sizePicture;
            }
            mCamera.setPreviewCallback(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
//                    System.arraycopy(data, 0, nv21, 0, data.length);
                }
            });

            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
            isPreview = true;
        }

    }

    /**
     * 初始化录视频相关
     *
     * @param holder
     * @throws IOException
     */
    @SuppressLint("NewApi")
    public void initRecord(FaceView holder) throws IOException {
        mMediaRecorder = new MediaRecorder();
        mMediaRecorder.reset();
        if (mCamera != null) {
            mMediaRecorder.setCamera(mCamera);
        }
        mMediaRecorder.setOnErrorListener(this);
        mMediaRecorder.setPreviewDisplay(holder.getSurfaceHolder().getSurface());
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 视频源
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 音频源
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 视频输出格式
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 音频格式
        mMediaRecorder.setVideoSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);// 设置分辨率：
        if (sizePicture < 3000000) {//这里设置可以调整清晰度
            mMediaRecorder.setVideoEncodingBitRate(3 * 1024 * 512);
        } else if (sizePicture <= 5000000) {
            mMediaRecorder.setVideoEncodingBitRate(2 * 1024 * 512);
        } else {
            mMediaRecorder.setVideoEncodingBitRate(1024 * 512);
        }
        mMediaRecorder.setOrientationHint(270);// 输出旋转270度，保持竖屏录制
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 视频录制格式
        time = format.format(new Date());
        outFile = new File(PATH_VIDEO + File.separator + FILE_NAME + time + FILE_NAME_SUFEIX);
        mMediaRecorder.setOutputFile(outFile.getAbsolutePath());
        mMediaRecorder.prepare();
        try {
            mMediaRecorder.start();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 停止录制
     */
    public void stopRecord() {
        if (mMediaRecorder != null) {
            // 设置后不会崩
            mMediaRecorder.setOnErrorListener(null);
            mMediaRecorder.setOnInfoListener(null);
            mMediaRecorder.setPreviewDisplay(null);
            try {
                mMediaRecorder.stop();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (RuntimeException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 释放资源
     */
    public void releaseRecord() {
        if (mMediaRecorder != null) {
            mMediaRecorder.setOnErrorListener(null);
            mMediaRecorder.setOnErrorListener(null);
            mMediaRecorder.setOnInfoListener(null);
            mMediaRecorder.setPreviewDisplay(null);
            try {
                mMediaRecorder.release();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        mMediaRecorder = null;
    }


    /**
     * 创建文件存储路径
     */
    public void createRecordDir() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            // 创建文件
            try {
                videofileDir = new File(PATH_VIDEO);
                imagefileDir = new File(PATH_IMAGE);

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                videofileDir = new File(mContext.getFilesDir().getAbsolutePath());
                imagefileDir = new File(mContext.getFilesDir().getAbsolutePath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (!videofileDir.exists()) {
            videofileDir.mkdirs();
        }
        if (!imagefileDir.exists()) {
            imagefileDir.mkdirs();
        }

    }

    /**
     * 检测相机权限
     *
     * @return
     */

    private boolean checkCameraPermission() {
        int status = mContext.checkPermission(Manifest.permission.CAMERA, Process.myPid(), Process.myUid());
        if (PackageManager.PERMISSION_GRANTED == status) {
            return true;
        }

        return false;
    }

    /**
     * 获取相机实例
     *
     * @return
     */
    public Camera getCameraInstance() {
        return mCamera;
    }

    @Override
    public void onError(MediaRecorder mr, int what, int extra) {

    }

    /**
     * 创建缩略图
     *
     * @param kind
     * @return
     */
    public static Bitmap createVideoThumbnail(int kind) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setDataSource(outFile.getAbsolutePath());
            bitmap = retriever.getFrameAtTime(-1);
        } catch (IllegalArgumentException ex) {
            // Assume this is a corrupt video file
        } catch (RuntimeException ex) {
            // Assume this is a corrupt video file.
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException ex) {
                // Ignore failures while cleaning up.
            }
        }

        if (bitmap == null) return null;

        if (kind == MediaStore.Images.Thumbnails.MINI_KIND) {
            // Scale down the bitmap if it's too large.
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            int max = Math.max(width, height);
            if (max > 512) {
                float scale = 512f / max;
                int w = Math.round(scale * width);
                int h = Math.round(scale * height);
                bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
            }
        } else if (kind == MediaStore.Images.Thumbnails.MICRO_KIND) {
            bitmap = extractThumbnail(bitmap,
                    240,
                    240,
                    OPTIONS_RECYCLE_INPUT);
        }
        return bitmap;
    }

    /**
     * 保存bitmap到本地
     *
     * @param context
     * @return
     */
    public static String getThumbnail(Context context) {
        String savePath;
        File filePic;
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            savePath = PATH_IMAGE;
        } else {
            savePath = context.getApplicationContext().getFilesDir().getAbsolutePath() + PATH_IMAGE;
        }
        try {
            filePic = new File(savePath +File.separator+ FILE_NAME + time + ".jpg");
            if (!filePic.exists()) {
                filePic.getParentFile().mkdirs();
                filePic.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(filePic);
            Bitmap mBitmap = createVideoThumbnail(MediaStore.Images.Thumbnails.MICRO_KIND);
            if (null!=mBitmap){
                mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            }
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return filePic.getAbsolutePath();
    }
}
